#include <string.h>
#include <time.h>
#include "tda_incidencia.h"
#include "utils.h"

int TIN_Crear ( TIN* tin, int inci_id, tipo_inci_t inci_type, prior_inci_t inci_priority, int inci_user, int inci_assigned_user,
                char* inci_date_created, int inci_project_id, char* inci_summary, char* inci_description )
{
	tin->inci_id = inci_id;
	tin->inci_type = inci_type;
	tin->inci_priority = inci_priority;
	tin->inci_user = inci_user;
	tin->inci_assigned_user = inci_assigned_user;
	strmcpy(&tin->inci_date_created, inci_date_created);
	tin->inci_project_id = inci_project_id;
	strmcpy(&tin->inci_summary, inci_summary);
	strmcpy(&tin->inci_description, inci_description);
	tin->inci_resolved = TIN_INCOMPLETE; /*La creo como incomplete */
	tin->inci_date_solved = NULL;

	ls_Crear(&tin->inci_stat_hist, sizeof(inci_status_t));
	ls_Crear(&tin->inci_comm, sizeof(inci_comment_t));

    return RES_OK;
}

int LiberarComentarios(TListaSimple* comment)
{
    inci_comment_t commaux;

    if(ls_MoverCorriente(comment,LS_PRIMERO))
    {
        do{
            ls_ElemCorriente(*comment,&commaux);
            free(commaux.comm_date); /*libero la fecha*/
            free(commaux.comm_desc);/*libero la descripci�n*/
        }while (ls_MoverCorriente(comment,LS_SIGUIENTE));

        ls_Vaciar(comment);/*elimino la lista de comentarios*/
    }

    return RES_OK;

}

int LiberarEstados(TListaSimple* status)

{
    inci_status_t stataux;

    if(ls_MoverCorriente(status,LS_PRIMERO))
    {
        do{
            ls_ElemCorriente(*status,&stataux);
            free(stataux.stat_date); /*elimino la fecha del estado*/
        }while (ls_MoverCorriente(status,LS_SIGUIENTE));

        ls_Vaciar(status);/*elimino la lista de estados*/
    }

    return RES_OK;

}

int TIN_Liberar( TIN* tin )
{
    free(tin->inci_date_created); /*libero los char* que estan adentro del TIN, el rsto de los datos los elimina el programa*/
    free(tin->inci_summary);
    free(tin->inci_description);
    free(tin->inci_date_solved);
    LiberarComentarios(&tin->inci_comm); /*libero la memoria dinamica de la lista de comentarios y la lista*/
    LiberarEstados(&tin->inci_stat_hist);/*IDEM anterior con la lista de estados*/

    return 0;
}

int TIN_CambiarEstado( TIN* tin,const char* fecha,const int usuario_id,const stat_inci_t estado )
{
    inci_status_t stataux;
    int N;

    N=strlen(fecha); /*cargo datos de los estados*/
    stataux.stat_date=(char*)malloc(sizeof(char)*N+1);
    strcpy(stataux.stat_date,fecha);
    stataux.stat_user_id=usuario_id;
    stataux.stat_desc=estado;

    do
    {
        /*recorro el historial de Comentarios, para llegar al ultimo*/
    }
    while (ls_MoverCorriente(&tin->inci_stat_hist,LS_SIGUIENTE));

    ls_Insertar(&tin->inci_stat_hist,LS_SIGUIENTE,&stataux);/*agrego el nuevo estado*/

    return RES_OK;
}

int TIN_Resolver( TIN* tin, const char* fecha, int usuario_id, resol_inci_t resolucion )
{
    /*time_t tiempo;
    int longFecha;*/
    /*struct tm *tmPtr;*/
    int N;

    tin->inci_assigned_user=usuario_id;

    if (tin->inci_date_solved==NULL)
    {
        N=strlen(fecha);
        tin->inci_date_solved=malloc(sizeof(char)*(N+1));
    }
    strcpy(tin->inci_date_solved,fecha);
    /*longFecha = sizeof(char) * 17;
    tin->inci_date_solved = (char*)malloc(longFecha);
    if(!tin->inci_date_solved)
        return ERR_OUT_OF_MEMORY;


    tiempo = time(NULL);
    tmPtr = localtime(&tiempo);


    strftime(tin->inci_date_solved, longFecha, FORMATO_FECHA, tmPtr);
    */


    tin->inci_resolved=resolucion;
    return RES_OK;
}

int TIN_Comentar( TIN* tin, char* fecha, int usuario_id, char* comentario )
{
	inci_comment_t nuevoComentario;

	/* Aloco memoria para la fecha*/
    nuevoComentario.comm_date = (char*)malloc((strlen(fecha) + 1) * sizeof(char));
    if(!nuevoComentario.comm_date)
        return ERR_OUT_OF_MEMORY;

	strcpy(nuevoComentario.comm_date, fecha);

	/* Aloco memoria para el comentario */
    nuevoComentario.comm_desc = (char*)malloc((strlen(comentario) + 1) * sizeof(char));
    if(!nuevoComentario.comm_desc)
    {
        free(nuevoComentario.comm_date);
        return ERR_OUT_OF_MEMORY;
    }
	strcpy(nuevoComentario.comm_desc, comentario);

	nuevoComentario.comm_user_id=usuario_id;

	if (!ls_Insertar(&tin->inci_comm, LS_SIGUIENTE, &nuevoComentario)) /* Agrego a la lista de comentarios */
	{
	    free(nuevoComentario.comm_date);
	    free(nuevoComentario.comm_desc);
	    return -1;

	}

    return RES_OK;
}


int TIN_GetDatos ( TIN* tin, int* inci_id, tipo_inci_t* inci_type, prior_inci_t* inci_priority, int* inci_user, int* inci_assigned_user,
                    char** inci_date_created, int* inci_project_id, char** inci_summary, char** inci_description )

{
    *inci_id = tin->inci_id;
    *inci_type = tin->inci_type;
    *inci_priority = tin->inci_priority;
    *inci_user = tin->inci_user;
    *inci_assigned_user = tin->inci_assigned_user;
    *inci_date_created = tin->inci_date_created;
    *inci_project_id = tin->inci_project_id;
    *inci_summary = tin->inci_summary;
    *inci_description = tin->inci_description;

    return RES_OK;
}

int TIN_GetListaComentarios( const TIN* tin, TListaSimple* comentarios )
{
    inci_comment_t* pComentario;
    char* fechaComentario;
    char* descComentario;
    TListaSimple auxComentarios;
    pComentario = NULL;
    fechaComentario = NULL;
    descComentario = NULL;

    /* Copio la lista de comentarios para recorrerla sin modificar la original */
    memcpy(&auxComentarios, &tin->inci_comm, sizeof(auxComentarios));

    /* Muevo el corriente al primer elemento */
    if(!ls_MoverCorriente(&auxComentarios, LS_PRIMERO))
        return ERR_LISTA_VACIA;
    do
    {
        /* Aloco memoria para el comentario que voy a obtener */
        pComentario = (inci_comment_t*)malloc(sizeof(inci_comment_t));
        if(!pComentario)
            return ERR_OUT_OF_MEMORY;
        /* Obtengo el comentario corriente */
        ls_ElemCorriente(auxComentarios, pComentario);

        /* Copio fisicamente los strings internos del comentario */
        fechaComentario = (char*)malloc(sizeof(char) * strlen(pComentario->comm_date) + 1);
        if(!fechaComentario)
        {
            free(pComentario);
            return ERR_OUT_OF_MEMORY;
        }
        strcpy(fechaComentario, pComentario->comm_date);
        pComentario->comm_date = fechaComentario;

        descComentario = (char*)malloc(sizeof(char) * strlen(pComentario->comm_desc) + 1);
        if(!descComentario)
        {
            free(pComentario);
            free(fechaComentario);
            return ERR_OUT_OF_MEMORY;
        }
        strcpy(descComentario, pComentario->comm_desc);
        pComentario->comm_desc = descComentario;

        /* Inserto el comentario en la nueva lista */
        if(!ls_Insertar(comentarios, LS_SIGUIENTE, pComentario))
        {
            free(pComentario);
            free(fechaComentario);
            free(descComentario);
            return ERR_UNDEFINED;
        }
    }
    /* Mientras exista un elemento siguiente al corriente */
    while(ls_MoverCorriente(&auxComentarios, LS_SIGUIENTE));

    return RES_OK;
}

int TIN_GetListaEstados( const TIN* tin, TListaSimple* estados )
{
    inci_status_t* pEstado;
    char* fechaEstado;
    TListaSimple auxEstados;
    pEstado = NULL;
    fechaEstado = NULL;

    /* Copio la lista de estados para recorrerla sin modificar la original */
    memcpy(&auxEstados, &tin->inci_stat_hist, sizeof(auxEstados));

    /* Muevo el corriente al primer elemento */
    if(!ls_MoverCorriente(&auxEstados, LS_PRIMERO))
        return ERR_LISTA_VACIA;
    do
    {
        /* Aloco memoria para el estado que voy a obtener */
        pEstado = (inci_status_t*)malloc(sizeof(inci_status_t));
        if(!pEstado)
            return ERR_OUT_OF_MEMORY;
        /* Obtengo el estado corriente */
        ls_ElemCorriente(auxEstados, pEstado);

        /* Copio fisicamente los strings internos del estado */
        fechaEstado = (char*)malloc(sizeof(char) * strlen(pEstado->stat_date) + 1);
        if(!fechaEstado)
        {
            free(pEstado);
            return ERR_OUT_OF_MEMORY;
        }
        strcpy(fechaEstado, pEstado->stat_date);
        pEstado->stat_date = fechaEstado;

        /* Inserto el estado en la nueva lista */
        if(!ls_Insertar(estados, LS_SIGUIENTE, pEstado))/** PROBA OPCION 5 Y TE TIRA SEGMENTATION FAULT SEGURO ES POR LO DE
        DECLARAR A pEstado como puntero*/
        {
            free(pEstado);
            free(fechaEstado);
            return ERR_UNDEFINED;
        }
    }
    /* Mientras exista un elemento siguiente al corriente */
    while(ls_MoverCorriente(&auxEstados, LS_SIGUIENTE));

    return RES_OK;
}

int TIN_RealocarStrings( TIN* tin )
{
    TListaSimple* plsAux;
    char* aux;
    plsAux = NULL;
    aux = NULL;

    /* Aloco memoria para inci_date_created y copio */
    aux = (char*)malloc(sizeof(char) * strlen(tin->inci_date_created) + 1);
    if(!aux)
        return ERR_OUT_OF_MEMORY;
    strcpy(aux, tin->inci_date_created);
    tin->inci_date_created = aux;

    /* Aloco memoria para inci_summary y copio */
    aux = (char*)malloc(sizeof(char) * strlen(tin->inci_summary) + 1);
    if(!aux)
    {
        free(tin->inci_date_created);
        return ERR_OUT_OF_MEMORY;
    }
    strcpy(aux, tin->inci_summary);
    tin->inci_summary = aux;

    /* Aloco memoria para inci_date_created y copio */
    aux = (char*)malloc(sizeof(char) * strlen(tin->inci_description) + 1);
    if(!aux)
    {
        free(tin->inci_date_created);
        free(tin->inci_summary);
        return ERR_OUT_OF_MEMORY;
    }
    strcpy(aux, tin->inci_description);
    tin->inci_description = aux;

    /* Aloco memoria para inci_date_created y copio */
    if (tin->inci_date_solved)
    	aux = (char*)malloc(sizeof(char) * strlen(tin->inci_date_solved) + 1);
    else
    	aux = NULL;
   if(!aux)
    {
        free(tin->inci_date_created);
        free(tin->inci_summary);
        free(tin->inci_description);
        return ERR_OUT_OF_MEMORY;
    }
    strcpy(aux, tin->inci_date_solved);
    tin->inci_date_solved = aux;

    /* Aloco memoria para la lista de estados y copio */
   /* plsAux = (TListaSimple*)malloc(sizeof(TListaSimple));
    if(!plsAux)
    {
        free(tin->inci_date_created);
        free(tin->inci_summary);
        free(tin->inci_description);
        free(tin->inci_date_solved);
        return ERR_OUT_OF_MEMORY;
    }
    ls_Crear(plsAux, sizeof(sizeof(inci_status_t)));
    if(!TIN_GetListaEstados(tin, plsAux))
    {
        free(tin->inci_date_created);
        free(tin->inci_summary);
        free(tin->inci_description);
        free(tin->inci_date_solved);
        free(plsAux);
        return ERR_OUT_OF_MEMORY;
    }
    tin->inci_stat_hist = *plsAux;*/

    /* Aloco memoria para la lista de comentarios y copio */
    /*plsAux = (TListaSimple*)malloc(sizeof(TListaSimple));
    if(!plsAux)
    {
        free(tin->inci_date_created);
        free(tin->inci_summary);
        free(tin->inci_description);
        free(tin->inci_date_solved);
        return ERR_OUT_OF_MEMORY;
    }
    ls_Crear(plsAux, sizeof(sizeof(inci_comment_t)));
    if(!TIN_GetListaComentarios(tin, plsAux))
    {
        free(tin->inci_date_created);
        free(tin->inci_summary);
        free(tin->inci_description);
        free(tin->inci_date_solved);
        free(plsAux);
        return ERR_OUT_OF_MEMORY;
    }
    tin->inci_comm = *plsAux;*/

    return RES_OK;
}
